package com.cloud.util;

import lombok.SneakyThrows;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
  // 私钥
  public final static String PRIVATE_JSON = "{\"kty\":\"RSA\",\"n\":\"uQIibITf5osWdD-pyZnv_JWDl0QHBfLVRXQzaRKQLHP9nPlXj8V72P9Y13NTriQ7AayL5fAV9waRwIdbkSDXa8FQZdqU959d30dYmjLI7Sb25b5r3vnQQO0Jx_ccOgRmNL_yUUyzteuLlfjXj4_nxXi-GUHmKx7p7R-g0qC1Z3JUzJhGsZfF4tKi7x5Ia5ylzbz0x76yiQpgZMCttzgT22H0LCcU9ZwhgK1dmjSpVz8-bRA8k5992c4OmAzEEspiCXzbjgrBucKSt5y7BZCy9NXVGH4QxavY3aFRoyEi1UHzrRimd9xEqudlyPPPu1DxvfcIK66lbPEDBG_CsqeiKw\",\"e\":\"AQAB\",\"d\":\"Ta8CQlvm4hisBIMI6aCMPxyOxTDo3AwTllbNEYUcabYIm2WtaS6sqrjJlqoTzI7lAfZwRcwyhOfKwrNzdPR70AC7oBEQtQtDcPI114WUjdPrHxv-koGF-wUtMrxlq0zWl7azaoTQ_wXZNk9nQB5WXTouZE-h9KBF7G336wlVMop8-CySiXWBSGi8iOQZPfTdMZuHWSo7zMq_8eBpQhJTQj_XkyrOZSiUjc8EWuRtl-aj5d-ng4NLfOeMbi5BjNIButDIEe5DrCJofALpOmciP2j2WZFNob68VeRrmtUFRVE8wnd9PkTHQcfzwjEMBGvXkjmFu2fB6tCtF8BcucaweQ\",\"p\":\"86ACflTxuIHggWKJbxJuKfqYwCBdDGwm5BnewQFwN0TkOFbSekit0DTydnxk2NDXqpgeahQyrNqsETmAF26KLJt5GWEu652v_gwryYPAwPJQAcmB8_PejUtLSSNdnwAvdHugyKemD_dorCzwaez6UlC8sELdO6caanFTYh7k0CM\",\"q\":\"wmfmSZP1T2WkwVjtHPE2TlRcQEHfcS3zFYvTsdi4q_YU2u_wDJ8gMVZDz6HeFKDEQ3InF2EHo4b0K493evpL_YMXE69G1PnEg9GAAwHnfntyxVN7Nx9zAq2XSueuCwb4-nyGnAfVSxoQ7F-nVbxUUzU7uHppf15gPdcT6EDJAlk\",\"dp\":\"nDJApwKLH8KVUB7_AmmMm_mBKd0WCzrkDGbRvGjRq33N3Jk9xQ0H82-e7HyAo8nyG_v_s_9TJiPlIf39tAg5KrRbhfwa-xFUnsrq3_5K_OnehebOHLyEOY7GrBOymJij1EjXIw7pl18Giy0czq0TKOd-snuMIAzZENmrnkM0bIU\",\"dq\":\"v6-K1gnZ28uxRCPWyK7eiSWNQJ6zHvnbsecJeVbj4EroDWiAHTHZoEwa2OQWAejzHD22Zcr6qTcsEreHa-7YdsOHQZWWFfGg3wj3W__IrmIyrHbAC34q_P0FLIp8hcr-PJ4EbF0c5sxw22EFsffcfZ8Dn8azty7rXo5vxpX6nSE\",\"qi\":\"gwy18qgeXaMpbQvqxQy7Hil8LggJgR7V-5dxA7T4DoHZeJoJuXbHM0iXEq7288h_VdHjUbVOBUsXQsTsIwu4OsesfhyXgvfEo7F_4Eqnv7DBGOFxT-juDVaCzMWYT2GAA6ddg5v6BcB8f2nMEe24dx3Ia_QNADSh6kBkBN7nSaY\"}";
  // 公钥
  public final static String PUBLIC_JSON = "{\"kty\":\"RSA\",\"n\":\"uQIibITf5osWdD-pyZnv_JWDl0QHBfLVRXQzaRKQLHP9nPlXj8V72P9Y13NTriQ7AayL5fAV9waRwIdbkSDXa8FQZdqU959d30dYmjLI7Sb25b5r3vnQQO0Jx_ccOgRmNL_yUUyzteuLlfjXj4_nxXi-GUHmKx7p7R-g0qC1Z3JUzJhGsZfF4tKi7x5Ia5ylzbz0x76yiQpgZMCttzgT22H0LCcU9ZwhgK1dmjSpVz8-bRA8k5992c4OmAzEEspiCXzbjgrBucKSt5y7BZCy9NXVGH4QxavY3aFRoyEi1UHzrRimd9xEqudlyPPPu1DxvfcIK66lbPEDBG_CsqeiKw\",\"e\":\"AQAB\"}";


  /**
   * 生成token
   *
   * @param userId    用户id
   * @param username 用户名字
   * @return
   */
  @SneakyThrows
  public static String sign(Long userId, String username) {
    // 1、 创建jwtclaims  jwt内容载荷部分
    JwtClaims claims = new JwtClaims();
    // 是谁创建了令牌并且签署了它
    claims.setIssuer("itbaizhan");
    // 令牌将被发送给谁
    claims.setAudience("audience");
    // 失效时间长 （分钟）
    claims.setExpirationTimeMinutesInTheFuture(60 * 24 * 7);
    // 令牌唯一标识符
    claims.setGeneratedJwtId();
    // 当令牌被发布或者创建现在
    claims.setIssuedAtToNow();
    // 再次之前令牌无效
    claims.setNotBeforeMinutesInThePast(2);
    // 主题
    claims.setSubject("shopping");
    // 可以添加关于这个主题得声明属性
    claims.setClaim("userId", userId);
    claims.setClaim("username", username);


    // 2、签名
    JsonWebSignature jws = new JsonWebSignature();
    //赋值载荷
    jws.setPayload(claims.toJson());


    // 3、jwt使用私钥签署
    PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(PRIVATE_JSON)).getPrivateKey();
    jws.setKey(privateKey);


    // 4、设置关键 kid
    jws.setKeyIdHeaderValue("keyId");


    // 5、设置签名算法
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    // 6、生成jwt
    String jwt = jws.getCompactSerialization();
    return jwt;
   }




  /**
   * 解密token，获取token中的信息
   *
   * @param token
   */
  @SneakyThrows
  public static Map<String, Object> verify(String token){
    // 1、引入公钥
    PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(PUBLIC_JSON)).getPublicKey();
    // 2、使用jwtcoonsumer  验证和处理jwt
    JwtConsumer jwtConsumer = new JwtConsumerBuilder()
         .setRequireExpirationTime() //过期时间
         .setAllowedClockSkewInSeconds(30) //允许在验证得时候留有一些余地 计算时钟偏差  秒
         .setRequireSubject() // 主题生命
         .setExpectedIssuer("itbaizhan") // jwt需要知道谁发布得 用来验证发布人
         .setExpectedAudience("audience") //jwt目的是谁 用来验证观众
         .setVerificationKey(publicKey) // 用公钥验证签名  验证密钥
         .setJwsAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, AlgorithmIdentifiers.RSA_USING_SHA256))
         .build();
    // 3、验证jwt 并将其处理为 claims
    try {
      JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
      return jwtClaims.getClaimsMap();
     }catch (Exception e){
      return new HashMap();
     }
   }




  public static void main(String[] args){
    // 生成
    String baizhan = sign(1001L, "baizhan");
    System.out.println(baizhan);


    Map<String, Object> stringObjectMap = verify(baizhan);
    System.out.println(stringObjectMap.get("userId"));
    System.out.println(stringObjectMap.get("username"));
   }
}
